home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / util / arp / arp.c next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  14.3 KB  |  569 lines

  1. /* $Id: arp.c,v 3.2 1994/05/02 19:39:03 jraja Exp $
  2.  *
  3.  * arp.c --- arp utility for AmiTCP/IP
  4.  *
  5.  * Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  6.  *                  Helsinki University of Technology, Finland.
  7.  *                  All rights reserved.
  8.  *
  9.  * Created      : Sun Apr 18 05:08:20 1993 ppessi
  10.  * Last modified: Wed Feb 16 19:48:50 1994 ppessi
  11.  *
  12.  * $Log: arp.c,v $
  13.  * Revision 3.2  1994/05/02  19:39:03  jraja
  14.  * Update for the new net.lib
  15.  *
  16.  * Revision 3.1  1994/02/21  20:32:19  ppessi
  17.  * Changed the version tag.
  18.  *
  19.  * Revision 1.10  1993/11/07  00:19:45  ppessi
  20.  * Reverted back to scanf()
  21.  *
  22.  * Revision 1.9  1993/10/29  01:26:40  ppessi
  23.  * Implemented dumping of arp tables.
  24.  * Cleaned up code, fixed close() bug.
  25.  */
  26.  
  27. #include "arp_rev.h"
  28. static const char version[] = VERSTAG " "
  29.   "Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
  30.   "Helsinki University of Technology, Finland.\n"
  31.   "Copyright © 1984 The Regents of the University of California.\n"
  32.   "All rights reserved.\n";
  33.  
  34.  
  35. /*
  36.  * Copyright © 1984 Regents of the University of California.
  37.  * All rights reserved.
  38.  *
  39.  * This code is derived from software contributed to Berkeley by
  40.  * Sun Microsystems, Inc.
  41.  *
  42.  * Redistribution and use in source and binary forms, with or without
  43.  * modification, are permitted provided that the following conditions
  44.  * are met:
  45.  * 1. Redistributions of source code must retain the above copyright
  46.  *    notice, this list of conditions and the following disclaimer.
  47.  * 2. Redistributions in binary form must reproduce the above copyright
  48.  *    notice, this list of conditions and the following disclaimer in the
  49.  *    documentation and/or other materials provided with the distribution.
  50.  * 3. All advertising materials mentioning features or use of this software
  51.  *    must display the following acknowledgement:
  52.  *    This product includes software developed by the University of
  53.  *    California, Berkeley and its contributors.
  54.  * 4. Neither the name of the University nor the names of its contributors
  55.  *    may be used to endorse or promote products derived from this software
  56.  *    without specific prior written permission.
  57.  *
  58.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  59.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  60.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  61.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  62.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  63.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  64.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  65.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  66.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  67.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  68.  * SUCH DAMAGE.
  69.  */
  70.  
  71. /****** netutil.doc/arp *****************************************************
  72. *
  73. *  NAME
  74. *       Arp - address resolution display and control
  75. *
  76. *  SYNOPSIS
  77. *       arp hostname
  78. *       arp -a [netname | hostname]
  79. *       arp -d hostname
  80. *       arp -s hostname address [temp] [pub] 
  81. *       arp -f filename
  82. *
  83. *  DESCRIPTION
  84. *       Arp displays and modifies the Internet to hardware address
  85. *       translation tables used by the Address Resolution Protocol. The
  86. *       hardware address is a hexadecimal string with each octet separated
  87. *       by a colon, for instance 0:12:ff:a. The length of the address must
  88. *       be correct for the specified interface.
  89. *
  90. *  OPTIONS
  91. *        none If no options are specified (first form above), arp displays
  92. *             the current ARP entry for hostname.  The hostname must either
  93. *             appear in the hostname database (SEE hosts), or be a DARPA
  94. *             Internet address expressed in Internet standard "dot
  95. *             notation". Hostname can also be resolved by nameserver.
  96. *
  97. *       -a    Display all current ARP entries by reading the address mapping
  98. *             table of the specified (sub)network. `Hostname' is used to as
  99. *             default network specifier.
  100. *
  101. *       -d    If an ARP entry exists for the host called hostname, delete
  102. *             it. [This requires super-user privileges.]
  103. *
  104. *       -s    Create an ARP entry for the host called hostname with the
  105. *             hardware station address address. The hardware station address
  106. *             is given as hexadecimal bytes separated by colons. If an ARP
  107. *             entry already exists for hostname, the existing entry is
  108. *             updated with the new information. The entry is permanent
  109. *             unless the word temp is given in the command. If the word pub
  110. *             is specified, the entry is published, which means that this
  111. *             system will act as an ARP server responding to requests for
  112. *             hostname even though the host address is not its own.
  113. *
  114. *       -f    Read file filename and set multiple entries in the ARP tables.
  115. *             Entries in the file should be of the form:
  116. *
  117. *                  hostname address [temp] [pub]
  118. *
  119. *             Argument meanings are the same as for the -s option.
  120. *
  121. *  AUTHOR
  122. *       Arp was developed by the University of California, Berkeley, for the
  123. *       BSD Unix system.
  124. *
  125. *  SEE ALSO
  126. *       ifconfig, netif.protocols/arp, "net/if_arp.h"
  127. *
  128. *****************************************************************************
  129. *
  130. */
  131.  
  132. /*
  133.  * arp - display, set, and delete arp table entries
  134.  */
  135.  
  136. #ifdef AMIGA
  137. #if __SASC
  138. #include <proto/socket.h>
  139. #elif __GNUC__
  140. #include <inline/socket.h>
  141. #else
  142. #include <clib/socket_protos.h>
  143. #endif
  144. #include <clib/netlib_protos.h>
  145. #endif /* AMIGA */
  146.  
  147. #include <sys/param.h>
  148. #include <sys/socket.h>
  149. #include <sys/ioctl.h>
  150.  
  151. #include <arpa/inet.h>
  152. #include <netdb.h>
  153. #include <netinet/in.h>
  154. #include <net/if.h>
  155.  
  156. #include <errno.h>
  157. #include <stdlib.h>
  158. #include <stdio.h>
  159.  
  160. extern int errno;
  161.  
  162. static int file(char *name);
  163. static int set(int argc, char **argv);
  164. static void get(char *host);
  165. static void delete(char *host);
  166. static int arpreq_print(struct arpreq *ar, int bynumber);
  167. static void sana_print(const u_char *cp, int len);
  168. static int sana_aton(const char *a, u_char *n, u_char *lenp);
  169. static void usage(void);
  170. static void dump(char *name);
  171. char * strsep(register char **stringp, register const char *delim);
  172.  
  173. char usage_str[] = 
  174.   "usage: arp hostname\n"
  175.   "       arp -a [netname | hostname]\n"
  176.   "       arp -d hostname\n"
  177.   "       arp -s hostname address [temp] [pub]\n"
  178.   "       arp -f filename\n";
  179.  
  180. main(argc, argv)
  181.     int argc;
  182.     char **argv;
  183. {
  184.   int ch;
  185.  
  186.   while ((ch = getopt(argc, argv, "adsf")) != EOF)
  187.     switch((char)ch) {
  188.     case 'a': {
  189.       char *net;
  190.       char myname[MAXHOSTNAMELEN];
  191.  
  192.       if (argc > 3)
  193.     usage();
  194.       if (argc == 3) {
  195.     net = argv[2];
  196.       } else {
  197.     net = myname;
  198.     gethostname(myname, sizeof(myname));
  199.       }
  200.       dump(net);
  201.       exit(0);
  202.     }
  203.     case 'd':
  204.       if (argc != 3)
  205.     usage();
  206.       delete(argv[2]);
  207.       exit(0);
  208.     case 's':
  209.       if (argc < 4 || argc > 7)
  210.     usage();
  211.       exit(set(argc-2, &argv[2]) ? 1 : 0);
  212.     case 'f':
  213.       if (argc != 3)
  214.     usage();
  215.       exit (file(argv[2]) ? 1 : 0);
  216.     case '?':
  217.     default:
  218.       usage();
  219.     }
  220.   if (argc != 2)
  221.     usage();
  222.   get(argv[1]);
  223.   exit(0);
  224. }
  225.  
  226. /*
  227.  * Process a file to set standard arp entries
  228.  */
  229. static int
  230. file(char *name)
  231. {
  232.   FILE *fp;
  233.   int i, retval;
  234.   char line[100], arg[5][50], *args[5];
  235.  
  236.   if ((fp = fopen(name, "r")) == NULL) {
  237.     fprintf(stderr, "arp: cannot open %s\n", name);
  238.     exit(1);
  239.   }
  240.  
  241.   args[0] = &arg[0][0];
  242.   args[1] = &arg[1][0];
  243.   args[2] = &arg[2][0];
  244.   args[3] = &arg[3][0];
  245.   args[4] = &arg[4][0];
  246.  
  247.   retval = 0;
  248.   while(fgets(line, 100, fp) != NULL) {
  249.     i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], arg[3], arg[4]);
  250.     if (i < 2) {
  251.       fprintf(stderr, "arp: bad line: %s\n", line);
  252.       retval = 1;
  253.       continue;
  254.     }
  255.     if (set(i, args))
  256.       retval = 1;
  257.   }
  258.   fclose(fp);
  259.   return (retval);
  260. }
  261.  
  262. /*
  263.  * Set an individual arp entry 
  264.  */
  265. static int
  266. set(int argc, char **argv)
  267. {
  268.   struct arpreq ar;
  269.   struct hostent *hp;
  270.   struct sockaddr_in *sin;
  271.   u_char *ea;
  272.   int s;
  273.   char *host = argv[0], *eaddr = argv[1];
  274.  
  275.   argc -= 2;
  276.   argv += 2;
  277.   bzero((caddr_t)&ar, sizeof ar);
  278.   sin = (struct sockaddr_in *)&ar.arp_pa;
  279.   sin->sin_len = sizeof(*sin);
  280.   sin->sin_family = AF_INET;
  281.   sin->sin_addr.s_addr = inet_addr(host);
  282.   if (sin->sin_addr.s_addr == -1) {
  283.     if (!(hp = gethostbyname(host))) {
  284.       fprintf(stderr, "arp: %s: ", host);
  285.       herror((char *)NULL);
  286.       return (1);
  287.     }
  288.     bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  289.       sizeof sin->sin_addr);
  290.   }
  291.   ea = (u_char *)ar.arp_ha.sa_data;
  292.   if (sana_aton(eaddr, ea, &ar.arp_ha.sa_len))
  293.     return (1);
  294.   ar.arp_ha.sa_len += 2;
  295.   ar.arp_flags = ATF_PERM;
  296.   while (argc-- > 0) {
  297.     if (strncmp(argv[0], "temp", 4) == 0)
  298.       ar.arp_flags &= ~ATF_PERM;
  299.     else if (strncmp(argv[0], "pub", 3) == 0)
  300.       ar.arp_flags |= ATF_PUBL;
  301.     else if (strncmp(argv[0], "trail", 5) == 0)
  302.       ar.arp_flags |= ATF_USETRAILERS;
  303.     argv++;
  304.   }
  305.     
  306.   s = socket(AF_INET, SOCK_DGRAM, 0);
  307.   if (s < 0) {
  308.     perror("arp: socket");
  309.     exit(1);
  310.   }
  311.   if (IoctlSocket(s, SIOCSARP, (caddr_t)&ar) < 0) {
  312.     perror(host);
  313.     exit(1);
  314.   }
  315.   CloseSocket(s);
  316.  
  317.   return (0);
  318. }
  319.  
  320. /*
  321.  * Display an individual arp entry
  322.  */
  323. static void
  324. get(char *host)
  325. {
  326.   struct arpreq ar;
  327.   struct hostent *hp;
  328.   struct sockaddr_in *sin;
  329.   int s;
  330.  
  331.   bzero((caddr_t)&ar, sizeof ar);
  332.   sin = (struct sockaddr_in *)&ar.arp_pa;
  333.   sin->sin_len = sizeof(*sin);
  334.   sin->sin_family = AF_INET;
  335.   sin->sin_addr.s_addr = inet_addr(host);
  336.   if (sin->sin_addr.s_addr == -1) {
  337.     if (!(hp = gethostbyname(host))) {
  338.       fprintf(stderr, "arp: %s: ", host);
  339.       herror((char *)NULL);
  340.       exit(1);
  341.     }
  342.     bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, sizeof sin->sin_addr);
  343.   }
  344.   s = socket(AF_INET, SOCK_DGRAM, 0);
  345.   if (s < 0) {
  346.     perror("arp: socket");
  347.     exit(1);
  348.   }
  349.   if (IoctlSocket(s, SIOCGARP, (caddr_t)&ar) < 0) {
  350.     if (errno == ENXIO)
  351.       printf("%s (%s) -- no entry\n", host, inet_ntoa(sin->sin_addr));
  352.     else
  353.       perror("SIOCGARP");
  354.     exit(1);
  355.   }
  356.   CloseSocket(s);
  357.  
  358.   (void)arpreq_print(&ar, 0);
  359. }
  360.  
  361. /*
  362.  * Delete an arp entry 
  363.  */
  364. static void
  365. delete(char *host)
  366. {
  367.   struct arpreq ar;
  368.   struct hostent *hp;
  369.   struct sockaddr_in *sin;
  370.   int s;
  371.  
  372.   bzero((caddr_t)&ar, sizeof ar);
  373.   sin = (struct sockaddr_in *)&ar.arp_pa;
  374.   sin->sin_len = sizeof(*sin);
  375.   sin->sin_family = AF_INET;
  376.   sin->sin_addr.s_addr = inet_addr(host);
  377.   if (sin->sin_addr.s_addr == -1) {
  378.     if (!(hp = gethostbyname(host))) {
  379.       fprintf(stderr, "arp: %s: ", host);
  380.       herror((char *)NULL);
  381.       exit(1);
  382.     }
  383.     bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  384.       sizeof sin->sin_addr);
  385.   }
  386.   s = socket(AF_INET, SOCK_DGRAM, 0);
  387.   if (s < 0) {
  388.     perror("arp: socket");
  389.     exit(1);
  390.   }
  391.   if (IoctlSocket(s, SIOCDARP, (caddr_t)&ar) < 0) {
  392.     if (errno == ENXIO)
  393.       printf("%s (%s) -- no entry\n",
  394.          host, inet_ntoa(sin->sin_addr));
  395.     else
  396.       perror("SIOCDARP");
  397.     exit(1);
  398.   }
  399.   CloseSocket(s);
  400.   printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
  401. }
  402.  
  403. /*
  404.  * Dump the entire arp table
  405.  */
  406. static void 
  407. dump(char *host)
  408. {
  409.   struct arptabreq atr; 
  410.   struct arpreq *ar;
  411.   struct sockaddr_in *sin;
  412.   int s, bynumber;
  413.   long n;
  414.   
  415.   bzero((caddr_t)&atr, sizeof atr);
  416.  
  417.   /* Identify the used interface according the host/net name */
  418.   sin = (struct sockaddr_in *)&atr.atr_arpreq.arp_pa;
  419.   sin->sin_len = sizeof(*sin);
  420.   sin->sin_family = AF_INET;
  421.   sin->sin_addr.s_addr = inet_addr(host);
  422.   if (sin->sin_addr.s_addr == -1) {
  423.     struct hostent *hp;
  424.     struct netent *np = NULL;
  425.     if (!(hp = gethostbyname(host)) &&
  426.     !(np = getnetbyname(host))) {
  427.       fprintf(stderr, "arp: %s: ", host);
  428.       herror((char *)NULL);
  429.       exit(1);
  430.     }
  431.     if (hp) 
  432.       bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, sizeof sin->sin_addr);
  433.     else
  434.       bcopy((char *)&np->n_net, (char *)&sin->sin_addr, sizeof np->n_net);
  435.   }
  436.  
  437.   s = socket(AF_INET, SOCK_DGRAM, 0);
  438.   if (s < 0) {
  439.     perror("arp: socket");
  440.     exit(1);
  441.   }
  442.  
  443.   if (IoctlSocket(s, SIOCGARPT, (caddr_t)&atr) < 0) {
  444.     perror("SIOCGARPT");
  445.     exit(1);
  446.   }
  447.  
  448.   n = atr.atr_size = atr.atr_inuse;
  449.   if (n) {
  450.     ar = atr.atr_table = malloc(sizeof(*ar) * n);
  451.     if (!ar) {
  452.       perror("arp: malloc");
  453.       exit(1);
  454.     }
  455.     if (IoctlSocket(s, SIOCGARPT, (caddr_t)&atr) < 0) {
  456.       perror("SIOCGARPT");
  457.       exit(1);
  458.     }
  459.     /* Entries may be deleted */
  460.     n = max(n, atr.atr_inuse);
  461.   }
  462.   CloseSocket(s);
  463.  
  464.   bynumber = 0;
  465.   while (n-- > 0) {
  466.     bynumber = arpreq_print(ar++, bynumber);
  467.   }
  468. }
  469.  
  470. static int
  471. arpreq_print(struct arpreq *ar, int bynumber)
  472. {
  473.   struct sockaddr_in *sin;
  474.   struct hostent *hp;
  475.   char *host;
  476.  
  477.   sin = (struct sockaddr_in *)&ar->arp_pa;
  478.  
  479.   if (bynumber == 0)
  480.     hp = gethostbyaddr((caddr_t)&sin->sin_addr, 
  481.                sizeof(struct in_addr), AF_INET);
  482.   else
  483.     hp = 0;
  484.  
  485.   if (hp)
  486.     host = hp->h_name;
  487.   else {
  488.     host = "?";
  489.     if (h_errno == TRY_AGAIN)
  490.       bynumber = 1;
  491.   }
  492.  
  493.   printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
  494.   if (ar->arp_flags & ATF_COM)
  495.     sana_print(ar->arp_ha.sa_data, ar->arp_ha.sa_len - 2);
  496.   else
  497.     printf("(incomplete)");
  498.   if (ar->arp_flags & ATF_PERM)
  499.     printf(" permanent");
  500.   if (ar->arp_flags & ATF_PUBL)
  501.     printf(" published");
  502.   if (ar->arp_flags & ATF_USETRAILERS)
  503.     printf(" trailers");
  504.   printf("\n");
  505.  
  506.   return bynumber;
  507. }
  508.  
  509. static void
  510. sana_print(const u_char *cp, int len)
  511. {
  512.   char format[] = 
  513.     "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx";
  514.   int i; long o[16];
  515.  
  516.   if (len) {
  517.     format[4*len - 1] = '\0';
  518.     for (i = 0; i < len; i++)
  519.       o[i] = cp[i];
  520.     vprintf(format, (va_list)o);
  521.   }
  522. }
  523.  
  524. static int
  525. sana_aton(const char *str, u_char *n, u_char *lenp)
  526. {
  527.   int i, chars, o[16];
  528.   u_char c;
  529.   const char *a = str;
  530.  
  531.   for (i = 0; i < 16; a++) {
  532.     o[i] = chars = 0;
  533.     while ((c = *a - '0') <= 9 
  534.       || (c = c - 'A' + '0' + 10) >= 9 && c < 16  /*ABCDEF*/
  535.       || (c = c - 'a' + 'A') >= 9 && c < 16) /*abcdef*/ {
  536.       a++; chars++;
  537.       o[i] = (o[i] << 4) + c;
  538.       if (o[i] >= 0x100)
  539.     return 1;
  540.     }
  541.     if (!chars)
  542.       return 1;
  543.     i++;
  544.     if (*a == '\0')
  545.       break;
  546.     else if (*a == ':')
  547.       continue;
  548.     return 1;
  549.   }
  550.  
  551.   if (i >= 16) {
  552.     fprintf(stderr, "arp: invalid SANA-II address '%s'\n", str);
  553.     return (1);
  554.   }
  555.  
  556.   *lenp = i;
  557.   while (i-- > 0)
  558.     n[i] = o[i];
  559.   return 0;
  560. }
  561.  
  562. static void
  563. usage(void)
  564. {
  565.   printf(usage_str);
  566.  
  567.   exit(1);
  568. }
  569.